package com.firemoss.atonement.entitymanager.mapper
{
	import com.firemoss.atonement.entitymanager.IEntityManager;
	import com.firemoss.atonement.mapper.DefaultGraphedInstanceFactory;
	import com.firemoss.atonement.mapper.IGraphedInstanceFactory;
	import com.firemoss.atonement.metadata.AtonementMetadata;
	import com.firemoss.atonement.metadata.EntityMetadata;
	import com.firemoss.atonement.metadata.Property;
	
	import org.as3commons.reflect.Type;
	
	public class GraphedEntityInstanceFactory extends DefaultGraphedInstanceFactory implements IGraphedInstanceFactory
	{
		public var entityManager : IEntityManager
		
		public function GraphedEntityInstanceFactory( entityManager : IEntityManager )
		{
			this.entityManager = entityManager
		}
		
		override public function createByTargetClass(source:*, targetClass:Class):*
		{
			var sourceType : Type = Type.forInstance( source )
			var targetType : Type = Type.forClass( targetClass )
				
			// refactor types to emd
			var sourceEmd : EntityMetadata = entityManager.getEntityMetadata( source )
			var targetEmd : EntityMetadata = entityManager.getEntityMetadata( new targetClass() );
				
			if ( !sourceEmd )
			{
				throw new Error( "Can't merge entity of type " + Type.forInstance( source ).fullName + ", as it doesn't appear to be an entity.  Please give it an identifier property." );
			}
			if ( !targetEmd )
			{
				throw new Error( "Can't merge entity of type " + Type.forClass( targetClass ).fullName + ", as it doesn't appear to be an entity.  Please give it an identifier property." );
			}
			
			var entity : Object = entityManager.get( targetClass, source[ sourceEmd.idPropertyName ] )
				
			if ( entity )
			{
				return entity
			}
			else
			{
				// TODO:  check for null id
				if ( sourceType == targetType )
				{
					entity = source
					entityManager.put( entity )
				}
				else
				{
					entity = super.createByTargetClass( source, targetClass )
					entity[ targetEmd.idPropertyName ] = source[ sourceEmd.idPropertyName ]
					entityManager.put( entity )
				}
				
				return entity
			}
		}
	}
}